function ScrollPanel(p_ctx, p_left, p_top)
{	
/*======================================== PRIVATE ==========================================*/
	this.horizontal_scrollbar= false;
	this.vertical_scrollbar = false;
	this.vertical_scrolling_start_Y = null;
	this.horizontal_scrolling_start_X = null;

	this.back_color = "#CCCCCC";	// scrolling area background
	this.fore_color = "#999999";	// for the thumb	
	//this.arrow_color = "#333333";
	this.box_color = "#DDDDDD";

	this.scroll_bar_thickness = 20;
	this.MaxX = 10; // Min is always 0
	this.MaxY = 10; // Min is always 0
	this.PosX=0; //current position of horizontal scroller thumb
	this.PosY=0; //current position of vertical scroller thumb
	this.largePosChange = 2.5;

/*====================================== PROPERTIES =========================================*/
	this.getHasFocus =function() { return this.hasFocus? this.hasFocus : false; }
	this.setHasFocus = function(p_focus)  { this.hasFocus=p_focus; if (this.child) this.child.setHasFocus(p_focus); }
	this.setHasFocus(false);
	
	this.getChild = function() {  return this.child? this.child : null; }
	this.setChild = function (p_child)
	{
	    //if (p_child) alert('child of me scrollpanel being set to: ' + p_child.toString());

	    if (p_child)
	    {
	        this.child = p_child;
	        this.child.setContext(this.ctx);
	        this.child.setLeft(this.left);
	        this.child.setTop(this.top);
	    }
	}
	this.setChild(null);
	
	this.getHeight = function() { return  this.height; }
	this.setHeight = function(p_height) { if (p_height>=0) this.height=p_height; }
	this.setHeight(50);

	// width ---------------------------------------------------------------
	this.getWidth = function() { return  this.width; }
	this.setWidth = function(p_width) { if (p_width>=0) this.width=p_width; }
	this.setWidth(100);

	// left ---------------------------------------------------------------
	this.getLeft = function() { return this.left; }
	this.setLeft = function(p_left)
	{
		if (p_left >= 0)
		{ 
			this.left = p_left; 
			if (this.child) this.child.setLeft(this.left);
		}
	}	
	this.setLeft(p_left? p_left : 0);

	// top ----------------------------------------------------------------
	this.getTop = function() { return this.top; }
	this.setTop = function(p_top)
	{
		if (p_top >= 0)
		{ 
			this.top = p_top; 
			if (this.child) this.child.setTop(this.top);
		}
	}
	this.setTop(p_top? p_top : 0);
	
	// context -------------------------------------------------------------
	this.getContext = function() { return this.ctx; }
	this.setContext = function(p_ctx) 
	{ 
		if (p_ctx) 
		{
			this.ctx = p_ctx;
			if (this.child) this.child.setContext(this.ctx);
		}
		//big blue school hamilton : Cailin	
	}
	this.setContext (p_ctx);	

/*====================================== EVENTS =========================================*/
	this.onScroll = null;


/*====================================== METHODS =========================================*/
	this.slice_width = function() { return this.width-this.scroll_bar_thickness; }
	this.slice_height = function() { return this.height-this.scroll_bar_thickness; }
	this.x_offset = function() { return Math.max(0, (this.child.getWidth() - this.slice_width())) * (this.PosX/this.MaxX); }
	this.y_offset = function() { return Math.max(0, (this.child.getHeight() - this.slice_height())) * (this.PosY/this.MaxY); }
	this.horizontal_scroll_bar_length = function() { return (this.width-this.scroll_bar_thickness) * Math.min(1, ((this.width-this.scroll_bar_thickness) / this.child.getWidth())); }
	this.vertical_scroll_bar_length = function() { return (this.height-this.scroll_bar_thickness) * Math.min(1, ((this.height-this.scroll_bar_thickness) / this.child.getHeight())); }
	this.horizontal_scroll_bar_start = function() { return ((this.width-this.scroll_bar_thickness)- this.horizontal_scroll_bar_length()) * (this.PosX/this.MaxX); } // this is a relative coordinate, thus this.left not added
	this.vertical_scroll_bar_start = function() { return ((this.height-this.scroll_bar_thickness)- this.vertical_scroll_bar_length()) * (this.PosY/this.MaxY); } // this is a relative coordinate, this.left not added
			
	this.mouseEventAffectsChild = function(p_x, p_y) // Checks if event applies to the child. Note that the top left corner of the child is always the same as the scroll panel's top left corner. On further thought, is this really needed?
	{
		return (p_x <= Math.min(this.width-this.scroll_bar_thickness, this.child.getWidth()-this.x_offset()) && p_y <= Math.min(this.height-this.scroll_bar_thickness, this.child.getHeight()-this.y_offset()));
	}
	this.mouseOut = function() //no coordinates needed
	{
		//alert('scroll panel mouse out');
		//terminate scrolling
		this.horizontal_scrolling_start_X = null;
		this.vertical_scrolling_start_Y= null;

		if (this.child) 
			if (this.child.mouseOut) //no need to check if mouse out affects child, it definitely does!
				this.child.mouseOut(); 
		if (this.onMouseOut) this.onMouseOut();		
	}
	this.mouseOver = function()
	{
		if (this.child) 
			if (this.child.mouseOver)
				this.child.mouseOver();
		if (this.onMouseOver) this.onMouseOver();		
	}
			
	this.mouseMove = function(p_x, p_y)
	{
		if (this.horizontal_scrolling_start_X)
		{	
			var max_horizontal_diff = this.width - this.horizontal_scroll_bar_length();
			var horizontal_diff = (p_x - this.horizontal_scrolling_start_X)/(2);
			this.PosX = this.PosX + ((horizontal_diff / max_horizontal_diff ) * this.MaxX);
			if (this.PosX < 0) { this.PosX = 0; this.horizontal_scrolling_start_X = p_x;  }
			if (this.PosX > this.MaxX) { this.PosX = this.MaxX; this.horizontal_scrolling_start_X = p_x;  }
		}
		if (this.vertical_scrolling_start_Y)
		{	
			var max_vertical_diff = this.height - this.vertical_scroll_bar_length();
			var vertical_diff = (p_y - this.vertical_scrolling_start_Y)/(2);
			this.PosY = this.PosY + ((vertical_diff / max_vertical_diff ) * this.MaxY);
			if (this.PosY < 0) { this.PosY = 0; this.vertical_scrolling_start_Y = p_y;  }
			if (this.PosY > this.MaxY) { this.PosY = this.MaxY; this.vertical_scrolling_start_Y = p_y;  }
		}
		if (this.child) 
			if (this.mouseEventAffectsChild(p_x, p_y)) 
				if (this.child.mouseMove)
					this.child.mouseMove(p_x + this.x_offset(), p_y + this.y_offset());
		if (this.onMouseMove) this.onMouseMove(p_x, p_y);		
	}
	this.mouseDown = function(p_x, p_y)
	{
		if (this.child)
		{
			if (this.horizontal_scrollbar)
			{
				// check if mouseDown is on horizontal scrolling area
				if ( p_y>=this.height - this.scroll_bar_thickness && p_y<=this.height) // note that these are relative coordinate
				{	
					// check if mouseDown is also on horizontal scrolling THUMB
					if (p_x >= this.horizontal_scroll_bar_start() && p_x <= (this.horizontal_scroll_bar_start()+this.horizontal_scroll_bar_length()))
						this.horizontal_scrolling_start_X = p_x; //horizontal scrolling started at the point with the specified x coordinate
					else 
					{
						if (p_x > 0 && p_x < this.horizontal_scroll_bar_start()) 
							this.PosX = this.PosX - this.largePosChange;
						if (p_x > (this.horizontal_scroll_bar_start()+this.horizontal_scroll_bar_length()) && p_x < (this.width-this.scroll_bar_thickness))
							this.PosX = this.PosX + this.largePosChange;
						if (this.PosX < 0) this.PosX = 0;
						if (this.PosX > this.MaxX) this.PosX = this.MaxX;					
					}
				}				
			}
			if (this.vertical_scrollbar)
			{
				// check if  mouseDown is on vertical scrolling area
				if (p_x>=this.width - this.scroll_bar_thickness && p_x<=this.width) //again, note that these are relative coordinate
				{		
					// check if mouseDown is also on vertical scrolling THUMB
					if (p_y >= this.vertical_scroll_bar_start() && p_y <= (this.vertical_scroll_bar_start()+this.vertical_scroll_bar_length()))
						this.vertical_scrolling_start_Y = p_y; //horizontal scrolling started at the point with the specified x coordinate
					else 
					{
						if (p_y > 0 && p_y < this.vertical_scroll_bar_start()) 
							this.PosY = this.PosY - this.largePosChange;
						if (p_y > (this.vertical_scroll_bar_start()+this.vertical_scroll_bar_length()) && p_y < (this.height-this.scroll_bar_thickness))
							this.PosY = this.PosY + this.largePosChange;
						if (this.PosY < 0) this.PosY = 0;
						if (this.PosY > this.MaxY) this.PosY = this.MaxY;					
					}
				}
			}
			if (this.mouseEventAffectsChild(p_x, p_y)) 
				if (this.child.mouseDown)
					this.child.mouseDown(p_x + this.x_offset(), p_y + this.y_offset()); 
		}
		if (this.onMouseDown) this.onMouseDown(p_x, p_y);
	}
	this.mouseUp = function(p_x, p_y)
	{
		//terminate scrolling
		this.horizontal_scrolling_start_X = null;
		this.vertical_scrolling_start_Y= null;
				
		if (this.child) 
			if (this.mouseEventAffectsChild(p_x, p_y)) 
				if (this.child.mouseUp)
					this.child.mouseUp(p_x + this.x_offset(), p_y + this.y_offset());
		if (this.onMouseUp) this.onMouseUp(p_x, p_y);
		//alert(this.PosY);
	}
	
	this.keyPress = function(key)
	{
		if (this.child) if (this.child.keyPress) this.child.keyPress(key);
		if (this.onKeyPress) this.onKeyPress(key);		
	}
	this.keyDown = function(key)
	{
		if (this.child) if (this.child.keyDown) return (this.child.keyDown(key));
		if (this.onKeyDown) this.onKeyDown(key);
	}

	this.render = function ()
	{
	    //alert('about to render me scrollbar');
	    this.horizontal_scrollbar = false; //initial default
	    this.vertical_scrollbar = false;  //initial default

	    // ClearRect not needed since ui controller handles it

	    //alert('is my child null? ' + (this.child == null));
	    if (this.child != null)
	    {
	        //alert('rendering with an awareness of my child');
	        var slice_width = this.width - this.scroll_bar_thickness;
	        var slice_height = this.height - this.scroll_bar_thickness;
	        var x_offset = Math.max(0, (this.child.getWidth() - slice_width)) * (this.PosX / this.MaxX);
	        var y_offset = Math.max(0, (this.child.getHeight() - slice_height)) * (this.PosY / this.MaxY);

	        // draw thin border
	        this.ctx.strokeStyle = "black";

	        this.ctx.strokeRect(this.left, this.top, this.width, this.height);
	        this.ctx.fillStyle = "white";
	        this.ctx.fillRect(this.left, this.top, this.width, this.height);
	        this.ctx.strokeStyle = this.fore_color;

	        // set clipping area and translation
	        this.ctx.save();
	        this.ctx.beginPath();
	        this.ctx.rect(this.left, this.top, this.width, this.height);
	        this.ctx.clip();
	        this.ctx.translate(-x_offset, -y_offset);

	        this.child.render();
	        this.ctx.restore();

	        //draw the vertical scroll bar background
	        this.ctx.fillStyle = this.back_color;
	        this.ctx.fillRect(this.left + this.width - this.scroll_bar_thickness, this.top, this.scroll_bar_thickness, this.height);

	        if (this.height - this.scroll_bar_thickness <= this.child.getHeight()) //if vertical scroll bar needs to be drawn
	        {
	            this.vertical_scrollbar = true;
	            var vertical_scroll_bar_length = this.vertical_scroll_bar_length();
	            var vertical_scroll_bar_start = this.top + this.vertical_scroll_bar_start();

	            //draw vertical scroll bar
	            this.ctx.fillStyle = this.fore_color;
	            this.ctx.beginPath();
	            this.ctx.moveTo(this.left + this.width - this.scroll_bar_thickness / 2, vertical_scroll_bar_start);
	            this.ctx.lineTo(this.left + this.width - this.scroll_bar_thickness, vertical_scroll_bar_start + 5);
	            this.ctx.lineTo(this.left + this.width - this.scroll_bar_thickness, vertical_scroll_bar_start + vertical_scroll_bar_length - 5);
	            this.ctx.lineTo(this.left + this.width - this.scroll_bar_thickness / 2, vertical_scroll_bar_start + vertical_scroll_bar_length);
	            this.ctx.lineTo(this.left + this.width, vertical_scroll_bar_start + vertical_scroll_bar_length - 5);
	            this.ctx.lineTo(this.left + this.width, vertical_scroll_bar_start + 5);
	            this.ctx.closePath();
	            this.ctx.fill();
	        }

	        // draw horizontal scroll bar background
	        this.ctx.fillStyle = this.back_color;
	        this.ctx.fillRect(this.left, this.top + this.height - this.scroll_bar_thickness, this.width, this.scroll_bar_thickness);

	        if (this.width - this.scroll_bar_thickness <= this.child.getWidth()) //if horizontal scroll bar needs to be drawn
	        {
	            this.horizontal_scrollbar = true;
	            var horizontal_scroll_bar_length = this.horizontal_scroll_bar_length();
	            var horizontal_scroll_bar_start = this.left + this.horizontal_scroll_bar_start();

	            //draw horizontal scroll bar
	            this.ctx.fillStyle = this.fore_color;
	            this.ctx.beginPath();
	            this.ctx.moveTo(horizontal_scroll_bar_start, this.top + this.height - this.scroll_bar_thickness / 2);
	            this.ctx.lineTo(horizontal_scroll_bar_start + 5, this.top + this.height - this.scroll_bar_thickness);
	            this.ctx.lineTo(horizontal_scroll_bar_start + horizontal_scroll_bar_length - 5, this.top + this.height - this.scroll_bar_thickness);
	            this.ctx.lineTo(horizontal_scroll_bar_start + horizontal_scroll_bar_length, this.top + this.height - this.scroll_bar_thickness / 2);
	            this.ctx.lineTo(horizontal_scroll_bar_start + horizontal_scroll_bar_length - 5, this.top + this.height);
	            this.ctx.lineTo(horizontal_scroll_bar_start + 5, this.top + this.height);
	            this.ctx.closePath();
	            this.ctx.fill();
	        }

	        // draw scroll intersection box
	        this.ctx.fillStyle = this.box_color;
	        this.ctx.fillRect(this.left + this.width - this.scroll_bar_thickness, this.top + this.height - this.scroll_bar_thickness, this.scroll_bar_thickness, this.scroll_bar_thickness);

	    }
	}
	
	//this.render();
}